﻿using System;
using System.Collections.Generic;
using System.Text;
using Atosenet.PluginEngine;

namespace Atosenet.Protocol
{
    [PluginAttribute("Atosenet", "Atosenet.Protocol.ProtocolPacketWTPv1", "WRTU长江航道航标灯数据协议v1", PluginType.Protocol)]
    public class ProtocolPacketWTPv1 : ProtocolPacket
    {
        #region 成员

        private const byte WTP_HEADER_FLAG = 0x24;                  /* $ */
        private const byte WTP_PHAROS_WORKDATA_FLAG = 0x23;         /* # */
        private const byte WTP_END_FLAG = 0x2A;                     /* * */

        private const int WTP_T2S_HEADER_LENGTH = 7;        //for "Terminal to Server" mode, the header len is 7
        private const int WTP_T2S_END_LENGTH = 5;           //for "Terminal to Server" mode, the end len is 5

        private int _headerCounter = 0;
        private List<byte> _dataBuffer = new List<byte>();
        private int _endCounter = 0;
        private DateTime _timestamp;

        #endregion


        #region 初始化

        public ProtocolPacketWTPv1()
        { }

        #endregion


        #region 公开函数

        public override void Append(byte[] data, ref int offset)
        {
            while (offset < data.Length)
	        {
                switch (State)
	            {
                    case WTPv1PacketState.WaitForHeader:
                        if (data[offset++] == WTP_HEADER_FLAG)
                        {
                            CreateHeader();
                            State = WTPv1PacketState.Header;
                        }
                        break;

                    case WTPv1PacketState.Header:
                        if (AppendHeader(data, ref offset))
                        {
                            CreateData();
                            State = WTPv1PacketState.Data;
                        }
                        break;

                    case WTPv1PacketState.Data:
                        if (AppendData(data, ref offset))
                        {
                            CreateEnd();
                            State = WTPv1PacketState.End;
                        }
                        break;

                    case WTPv1PacketState.End:
                        if (AppendEnd(data, ref offset))
                        {
                            _timestamp = DateTime.Now;
                            State = WTPv1PacketState.Completed;                            
                        }
                        break;

                    case WTPv1PacketState.Completed:
                    case WTPv1PacketState.Error:
                    default:
                        return;
	            }   
	        }   
        }

        public override byte[] Generate()
        {
            if (HEADER == null || DATA == null || END == null)
                return new byte[0];

            byte[] data = new byte[HEADER.Length + DATA.Length + END.Length + 2];
            data[0] = WTP_HEADER_FLAG;
            Array.Copy(HEADER, 0, data, 1, HEADER.Length);
            Array.Copy(DATA, 0, data, 1 + HEADER.Length, DATA.Length);
            data[1 + HEADER.Length + DATA.Length] = WTP_END_FLAG;
            Array.Copy(END, 0, data, HEADER.Length + DATA.Length + 2, END.Length);
            return data;
        }

        public override void Reset()
        {
            State = WTPv1PacketState.WaitForHeader;
        }

        public override object Clone()
        {
            ProtocolPacketWTPv1 packet = CreatePacket(this.RawData);
            packet._timestamp = this._timestamp;
            return packet;
        }

        public override string ToString()
        {
            return string.Format("WTPv1 Protocol Packet{0}([HEADER]={1},[DATA]={2},[END]={3})",
                Environment.NewLine,
                Converter.ConvertToHexString(HEADER),
                Converter.ConvertToHexString(DATA),
                Converter.ConvertToHexString(END));
        }

        #endregion


        #region 静态函数

        public static ProtocolPacketWTPv1 CreatePacket(byte[] header, byte[] data, byte[] end)
        {
            ProtocolPacketWTPv1 packet = new ProtocolPacketWTPv1();
            packet.HEADER = header;
            packet.DATA = data;
            packet.END = end;
            return packet;
        }

        public static ProtocolPacketWTPv1 CreatePacket(byte[] rawData)
        {
            ProtocolPacketWTPv1 packet = new ProtocolPacketWTPv1();
            int offset = 0;
            packet.Append(rawData, ref offset);
            return packet;
        }

        #endregion


        #region 核心函数

        private void CreateHeader()
        {
            HEADER = new byte[WTP_T2S_HEADER_LENGTH];
            _headerCounter = 0;
        }

        private bool AppendHeader(byte[] data, ref int offset)
        {
            while (offset < data.Length)
            {
                HEADER[_headerCounter++] = data[offset++];

                if (_headerCounter >= WTP_T2S_HEADER_LENGTH)
                    return true;
            }
            return false;
        }

        private void CreateData()
        {
            _dataBuffer.Clear();
        }

        private bool AppendData(byte[] data, ref int offset)
        {
            while (offset < data.Length)
            {
                byte d = data[offset++];

                if (d == WTP_END_FLAG)
                {
                    DATA = _dataBuffer.ToArray();
                    return true;
                }
                else
                {
                    _dataBuffer.Add(d);
                }
            }
            return false;
        }

        private void CreateEnd()
        {
            END = new byte[WTP_T2S_END_LENGTH];
            _endCounter = 0;
        }

        private bool AppendEnd(byte[] data, ref int offset)
        {
            while (offset < data.Length)
            {
                END[_endCounter++] = data[offset++];

                if (_endCounter >= WTP_T2S_END_LENGTH)
                    return true;
            }
            return false;
        }

        #endregion


        #region 属性

        public byte[] HEADER
        {
            get;
            set;
        }

        public byte[] DATA
        {
            get;
            set;
        }

        public byte[] END
        {
            get;
            set;
        }

        public override byte[] PacketFlag
        {
            get { return new byte[] { WTP_HEADER_FLAG }; }
        }

        public override bool IsCompleted
        {
            get { return State == WTPv1PacketState.Completed; }
        }

        public override string PacketDataHex
        {
            get { return Converter.ConvertToHexString(RawData); }
        }

        public override bool HasError
        {
            get { return State == WTPv1PacketState.Error; }
        }

        public override bool IsValid
        {
            get { return !HasError; }
        }

        public override byte[] RawData
        {
            get { return Generate(); }
        }

        public override DateTime Timestamp
        {
            get { return _timestamp; }
        }

        private WTPv1PacketState State
        {
            get;
            set;
        }

        #endregion


        #region 附加对象

        public enum WTPv1PacketState
        {
            WaitForHeader = 0,
            Header = 1,
            Data = 2,
            End = 3,
            Completed = 4,
            Error = 10
        }

        #endregion
    }
}
